#ifndef GCOMPILER_HEADER_GLEXER_H
#define GCOMPILER_HEADER_GLEXER_H


//---------------------------------------------------------
//	Lexer
//---------------------------------------------------------

// Selection include Sequence :
// Selection::first == Sequence::first, confusion!!!
// Selection include Pharse:
// Multiple1::type == Multiple2::type, confusion!!!
// Multiple::type == Sequence::first, confusion!!!
// Sequence include Multiple:
// Multiple::type == Sequence::next by Pharse, confusion!!!

//#define push_error printf
namespace GLexer
{
	//---------------------------------------------------------
	//	Parser context.
	class parser_context
	{
	public:
		parser_context() {}
		virtual ~parser_context() {}
	public:
		virtual void * prepare()							= 0;
		virtual bool rollback(void * session)				= 0;
		//virtual bool commit(void * data, unsigned int len)	= 0;
		virtual bool commit()								= 0;
		virtual void push()									= 0;
		virtual void push_error(const char * errstr)		= 0;
		//virtual void push_error(const char *)				= 0;
	};


	//---------------------------------------------------------
	// Default Reducer
	template<typename _Lexical>
	struct reducer
	{
		template <typename _Context, typename _InputIterator>
		static bool reduce(_Context&, _InputIterator&, _InputIterator&)
		{
			return true;
		}
	};


	//---------------------------------------------------------
	template<typename _Lexical, typename _Context, typename _InputIterator>
	bool dispose(_Context& context, _InputIterator& first, _InputIterator& last)
	{
		void * session = context.prepare();
		if (reducer<_Lexical>::reduce(context, first, last))
		{
			context.commit();
			return true;
		}
		else
		{
			context.rollback(session);
			return false;
		}
	};

//=================================================================================================================	

	template <int _Code>
	struct symbol
	{
		template<typename _ForwardIterator>
		static bool match(_ForwardIterator first, _ForwardIterator * next)
		{
			return (_Code == *first) ? (*next = ++first, true) : false;
		}
	};


	//=========================================================
	//	Token
	//=========================================================


	//---------------------------------------------------------
	//	Token
	template <typename _Nt1,  typename _Nt2 = void, typename _Nt3 = void, typename _Nt4 = void,
		typename _Nt5 = void, typename _Nt6 = void, typename _Nt7 = void, typename _Nt8 = void,
		typename _Nt9 = void, typename _Nt10= void, typename _Nt11= void, typename _Nt12= void,
		typename _Nt13= void, typename _Nt14= void, typename _Nt15= void, typename _Nt16= void,
		typename _Nt17= void, typename _Nt18= void, typename _Nt19= void, typename _Nt20= void,
		typename _Nt21= void, typename _Nt22= void, typename _Nt23= void, typename _Nt24= void,
		typename _Nt25= void, typename _Nt26= void, typename _Nt27= void, typename _Nt28= void,
		typename _Nt29= void, typename _Nt30= void, typename _Nt31= void, typename _Nt32= void>
	struct token
	{
		template<typename _Context, typename _ForwardIterator>
		static bool shift(_Context& context, _ForwardIterator first, _ForwardIterator * next)
		{
			return _Nt1::match(first, next)
					&& token<
						_Nt2 , _Nt3 , _Nt4 , _Nt5 , _Nt6 , _Nt7 , _Nt8 , _Nt9 ,
						_Nt10, _Nt11, _Nt12, _Nt13, _Nt14, _Nt15, _Nt16, _Nt17,
						_Nt18, _Nt19, _Nt20, _Nt21, _Nt22, _Nt23, _Nt24, _Nt25,
						_Nt26, _Nt27, _Nt28, _Nt29, _Nt30, _Nt31, _Nt32, void
					>::shift(context, *next, next);
		}
	};

	template <typename _Notation>
	struct token <_Notation,
		void, void, void, void, void, void, void, void, void, void, void, void, void, void, void,
		void, void, void, void, void, void, void, void, void, void, void, void, void, void, void, void>
	{
		template<typename _Context, typename _ForwardIterator>
		static bool shift(_Context&, _ForwardIterator first, _ForwardIterator * next)
		{
			return _Notation::match(first, next);
		}
	};


	//=========================================================
	//	Flows
	//=========================================================

	//---------------------------------------------------------
	//	Multiple
	template<typename _Lexical, unsigned int limits = 0>
	struct multiple
	{
		template<typename _Context, typename _ForwardIterator>
		static bool shift(_Context& context, _ForwardIterator first, _ForwardIterator * next)
		{
			_ForwardIterator temp = first;
			for (unsigned int i = 0; i < limits; i++)
			{
				if (_Lexical::shift(context, temp, next) && dispose<_Lexical>(context, temp, *next))
				{
					temp = *next;
				}
				else
				{
					*next = first;	//rewind
					return false;
				}
			}
			return true;
		}
	};

	template<typename _Lexical> 
	struct multiple<_Lexical, 1>
	{
		template<typename _Context, typename _ForwardIterator>
		static bool shift(_Context& context, _ForwardIterator first, _ForwardIterator * next)
		{
			if (_Lexical::shift(context, first, next) && dispose<_Lexical>(context, first, *next))
			{
				return true;
			}
			else
			{
				//push_error("multiple _Lexical, limits = 1 at pos '%s'\n", first);
				return false;
			}
		}
	};

	// no limits
	template<typename _Lexical>
	struct multiple<_Lexical, 0>
	{
		template<typename _Context, typename _ForwardIterator>
		static bool shift(_Context& context, _ForwardIterator first, _ForwardIterator * next)
		{
			while (_Lexical::shift(context, first, next) && dispose<_Lexical>(context, first, *next))
			{
				first = *next;
			}
			*next = first;	//rewind to prev step.
			return true;
		}
	};

	//---------------------------------------------------------
	// Sequence
	template <typename  _Lx1, typename _Lx2 = void, typename _Lx3 = void, typename _Lx4 = void,
		typename _Lx5 = void, typename _Lx6 = void, typename _Lx7 = void, typename _Lx8 = void,
		typename _Lx9 = void, typename _Lx10= void, typename _Lx11= void, typename _Lx12= void,
		typename _Lx13= void, typename _Lx14= void, typename _Lx15= void, typename _Lx16= void,
		typename _Lx17= void, typename _Lx18= void, typename _Lx19= void, typename _Lx20= void,
		typename _Lx21= void, typename _Lx22= void, typename _Lx23= void, typename _Lx24= void,
		typename _Lx25= void, typename _Lx26= void, typename _Lx27= void, typename _Lx28= void,
		typename _Lx29= void, typename _Lx30= void, typename _Lx31= void, typename _Lx32= void>
	struct sequence
	{
		template<typename _Context, typename _ForwardIterator>
		static bool shift(_Context& context, _ForwardIterator first, _ForwardIterator * next)
		{
			if (_Lx1::shift(context, first, next) && dispose<_Lx1>(context, first, *next))
			{
				return sequence<
					_Lx2 , _Lx3 , _Lx4 , _Lx5 , _Lx6 , _Lx7 , _Lx8 , _Lx9 , _Lx10, _Lx11, _Lx12, _Lx13, _Lx14, _Lx15, _Lx16, _Lx17,
					_Lx18, _Lx19, _Lx20, _Lx21, _Lx22, _Lx23, _Lx24, _Lx25, _Lx26, _Lx27, _Lx28, _Lx29, _Lx30, _Lx31, _Lx32, void
				>::shift(context, *next, next);
			}
			else
			{
				//push_error("sequence _Lx1 ~ _Lx32 failed at pos '%s'\n", first);
				return false;
			}
		}
	};

	template <typename _Lexical>
	struct sequence <_Lexical,
		void, void, void, void, void, void, void, void, void, void, void, void, void, void, void,
		void, void, void, void, void, void, void, void, void, void, void, void, void, void, void, void>
	{
		template<typename _Context, typename _ForwardIterator>
		static bool shift(_Context& context, _ForwardIterator first, _ForwardIterator * next)
		{
			if (_Lexical::shift(context, first, next) && dispose<_Lexical>(context, first, *next))
			{
				return true;
			}
			else
			{
				//push_error("sequence _Lexical failed at pos '%s'\n", first);
				return false;
			}
		}
	};

	//---------------------------------------------------------
	// Selection
	template <typename _Lx1,  typename _Lx2,        typename _Lx3 = void, typename _Lx4 = void,
		typename _Lx5 = void, typename _Lx6 = void, typename _Lx7 = void, typename _Lx8 = void,
		typename _Lx9 = void, typename _Lx10= void, typename _Lx11= void, typename _Lx12= void,
		typename _Lx13= void, typename _Lx14= void, typename _Lx15= void, typename _Lx16= void,
		typename _Lx17= void, typename _Lx18= void, typename _Lx19= void, typename _Lx20= void,
		typename _Lx21= void, typename _Lx22= void, typename _Lx23= void, typename _Lx24= void,
		typename _Lx25= void, typename _Lx26= void, typename _Lx27= void, typename _Lx28= void,
		typename _Lx29= void, typename _Lx30= void, typename _Lx31= void, typename _Lx32= void>
	struct selection
	{
		template<typename _Context, typename _ForwardIterator>
		static bool shift(_Context& context, _ForwardIterator first, _ForwardIterator * next)
		{
			if ((_Lx1::shift(context, first, next) && dispose<_Lx1>(context, first,*next)))
			{
				return true;
			}
			else
			{
				*next = first;	//rewind
				return selection <
					_Lx2 , _Lx3 , _Lx4 , _Lx5 , _Lx6 , _Lx7 , _Lx8 , _Lx9 , _Lx10, _Lx11, _Lx12, _Lx13, _Lx14, _Lx15, _Lx16, _Lx17,
					_Lx18, _Lx19, _Lx20, _Lx21, _Lx22, _Lx23, _Lx24, _Lx25, _Lx26, _Lx27, _Lx28, _Lx29, _Lx30, _Lx31, _Lx32, void
				>::shift(context, first, next);
			}
		}
	};

	template <typename _Lx1, typename _Lx2>
	struct selection <
		_Lx1, _Lx2, void, void, void, void, void, void, void, void, void, void, void, void, void, void,
		void, void, void, void, void, void, void, void, void, void, void, void, void, void, void, void>
	{
		template<typename _Context, typename _ForwardIterator>
		static bool shift(_Context& context, _ForwardIterator first, _ForwardIterator * next)
		{
			if ((_Lx1::shift(context, first, next) && dispose<_Lx1>(context, first,*next)))
			{
				return true;
			}
			else
			{
				*next = first;	//rewind
				if ( _Lx2::shift(context, first, next) && dispose<_Lx2>(context, first,*next))
				{
					return true;
				}
				else
				{
					*next = first;	//rewind
					//push_error("clear prev error\n");
					//push_error("selection _Lx1 ~ _Lx32 failed at pos '%s'\n", first);
					return false;
				}
			}
		}
	};

	//---------------------------------------------------------
	// Exclusion
	template <typename _Lexical>
	struct exclusion
	{
		template<typename _Context, typename _ForwardIterator>
		static bool shift(_Context& context, _ForwardIterator first, _ForwardIterator *)
		{
			_ForwardIterator temp = first;
			if (_Lexical::shift(context, first, &temp))
			{
				//push_error("exclusion _Lexical failed at pos '%s'\n", first);
				return false;
			}
			else
			{
				return true;
			}
		}
	};

	//---------------------------------------------------------
	// Inclusion
	template <typename _Lexical>
	struct inclusion
	{
		template<typename _Context, typename _ForwardIterator>
		static bool shift(_Context& context, _ForwardIterator first, _ForwardIterator *)
		{
			_ForwardIterator temp = first;
			if (_Lexical::shift<TC>(context, first, &temp))
			{
				return true;
			}
			else
			{
				//push_error("inclusion _Lexical failed at pos '%s'\n", first);
				return false;
			}
		}
	};

	//---------------------------------------------------------
	// Optional, none or one element
	template<typename _Lexical>
	struct optional
	{
		template<typename _Context, typename _ForwardIterator>
		static bool shift(_Context& context, _ForwardIterator first, _ForwardIterator * next)
		{
			if (!(_Lexical::shift(context, first, next) && dispose<_Lexical>(context, first, *next)))
			{
				*next = first;	//rewind
			}
			return true;
		}
	};

	//---------------------------------------------------------
	// at least one element
	template<typename _Lexical>
	struct oneormore
	{
		template<typename _Context, typename _ForwardIterator>
		static bool shift(_Context& context, _ForwardIterator first, _ForwardIterator * next)
		{
			if (_Lexical::shift(context, first, next) && dispose<_Lexical>(context, first, *next))
			{
				multiple<_Lexical, 0>::shift(context, *next, next);
				return true;
			}
			else
			{
				context.push_error("oneormore _Lexical failed\n");
				return false;
			}
		}
	};

	//---------------------------------------------------------
	// nulltoken
	struct nulltoken
	{
		template<typename _Context, typename _ForwardIterator>
		static bool shift(_Context&, _ForwardIterator, _ForwardIterator *)
		{
			return true;
		}
	};

	//---------------------------------------------------------
	// Helper template class
	template <typename _Lexical>
	struct parser
	{
		template<typename _Context, typename _ForwardIterator>
		static bool parse(_Context& context, _ForwardIterator first, _ForwardIterator * next)
		{
			*next = first;
			if (_Lexical::shift(context, first, next) && dispose<_Lexical>(context, first, *next))
			{
				return true;
			}
			else
			{
				context.push_error("parser _Lexical failed\n");
				return false;
			}
		}
	};



	//---------------------------------------------------------
#	define BEGIN_REDUCER(_Lexical)																	\
		template<> struct reducer<_Lexical>{														\
			template <typename _Context, typename _InputIterator>									\
			static bool reduce(_Context& context, _InputIterator& begin, _InputIterator& last) {	\
				(void)context; (void)begin; (void)last;
#	define END_REDUCER	}};



}	//end namespace GLexer

#endif	//ifndef GCOMPILER_HEADER_GLEXER_H

